#include <iostream>
#include <unistd.h>
#include <cassert>
#include <cstring>
#include <sys/wait.h>
#include <sys/types.h>
using namespace std;


//父进程进行读取，子进程负责写入
int main()
{
    //第一步：创建管道文件，打开读写端
    //fds[0]读   fds[1]写
    int fds[2];
    int n=pipe(fds);
    assert(n==0);

    //fork
    pid_t id=fork();
    assert(id>=0);
    if(id==0)
    {
        //子进程写入，先关闭读
        close(fds[0]);

        //子进程通信代码
        const char* s="我是子进程，我正在给你发信息";
        int cnt=0;
        while (true)
        {
            cnt++;
            char buffer[1024];//只有子进程能访问
            //格式化写入
            snprintf(buffer,sizeof(buffer),"chile->parent say: %s[%d][%d]",s,cnt,getpid());
            //子进程向【fd[1]】不断写，父进程【fd[0]】延迟读，导致写阻塞
            write(fds[1],buffer,strlen(buffer));

            //cout<<"count"<<cnt<<endl;
            //sleep(5);//延迟写，父进程read阻塞

            //break;//写一次直接关闭读端，读端read返回0,

        }
        //出来还是子进程
        close(fds[1]);//子进程关闭写端fd
        cout<<"子进程关闭了自己的写端"<<endl;
        exit(0);
        
    }

    //父进程读取
    close(fds[1]);
    //父进程通信代码
    while(true)
    {
        //sleep(3000);//写端不断写，读端延迟读，写端阻塞
        //sleep(2);//写端不断写，读端缓读，数据积累在一起被读出
        char buffer[1024];

        //如果管道中没有数据，读端在读，默认阻塞当前读进程由R->S状态
        //cout<<"parent_read_begin..."<<endl;
        ssize_t s= read(fds[0],buffer,sizeof(buffer)-1);//阻塞式调用
        //cout<<"parent_read_end..."<<endl;

        if(s>0)
        {
            buffer[s]=0;
            cout<<"父进程读到了# "<<buffer<<" | my_pid: "<<getpid()<<endl;
        }
        else if(s==0)
        {
            //读到了文件末尾
            cout<<"read: over "<<s<<endl;
            break;
        }
        break;//读一次直接退出，父进程准备关闭读端，os会发送信号杀掉写进程
    }
    //读未关闭
    // n=waitpid(id,nullptr,0);
    // assert(n==id);
    // close(fds[0]);



    //关闭读端，程序无效
    close(fds[0]);
    cout<<"父进程关闭写端"<<endl;
    int status=0;
    n=waitpid(id,&status,0);

    ////获取进程终止信号
    cout<<"waitpid->"<<n<<" : "<<(status&0x7f)<<endl;

    
    return 0;
}